using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;

namespace TCC.Framework
{
    /// <summary>
    /// 编辑器窗口管理工具
    /// </summary>
    [InitializeOnLoad]
    public class WindowsManager
    {
        /// <summary>
        /// 编辑器初始化事件
        /// </summary>
        public static TAction InitEditorEvent;

        /// <summary>
        /// 编辑器运行时事件
        /// </summary>
        public static TAction m_onEditorRuntime;

        /// <summary>
        /// 受保护资源数据表
        /// </summary>
        private static ProtectFileList fileList;

        public static ProtectFileList FileList
        {
            get
            {
                if(fileList==null)
                    fileList = AssetDatabase.LoadAssetAtPath<ProtectFileList>(EditorConfigFile.protectAssetListPath);
                return fileList;
            }
        }

        static WindowsManager()
        {
            InitEditorEvent?.Invoke();
            ExamineFramework();
            OnAssetsEvent.DeleteAssetEvent += DataTableDeleteEvent;
            OnAssetsEvent.CreateAssetEvent += OnCreateScript;
            EditorApplication.hierarchyWindowItemOnGUI += HierarchyItemChanged;
        }

        /// <summary>
        /// 检查框架目录路径
        /// </summary>
        /// <returns></returns>
        static bool ExamineFramework()
        {
            string[] guids = AssetDatabase.FindAssets("t:folder TCCFramework");

            if(guids.Length>1)
            {
                Log.Warning("当前项目存在相同文件夹【TCCFramework】，导致部分功能无法初始化！");
                return false;
            }
            string oldPath = AssetDatabase.GUIDToAssetPath(guids[0]);
            if (oldPath!=EditorConfigFile.frameworkRoot)
                AssetDatabase.MoveAsset(oldPath, EditorConfigFile.frameworkRoot);
            return true;
        }

        #region 工具入口
        [MenuItem("TCCFramework/Tools/数据编辑器")]
        public static void OpenTableEditor()
        {
            DataEditor.OpenWin(null);
        }

        [MenuItem("Assets/添加资源保护",false,2)]
        public static void AddAssetToProtectList()
        {
            Object obj= Selection.activeObject;
            if (obj != null)
                AddAssetProtectEditor.OpenWin(obj);
            else
                Log.Error("添加资源保护需要先选中受保护的资源！");
        }

        /// <summary>
        /// 打开本地化语言数据配置表编辑器
        /// </summary>
        [MenuItem("TCCFramework/配置本地化语言")]
        public static void OpenLanguaeTable()
        {
            LanguageDate date = AssetDatabase.LoadAssetAtPath<LanguageDate>(EditorConfigFile.LanguageTablePath);
            LanguageTable.OpenWin(date);
        }

        [MenuItem("TCCFramework/Tools/一键清理缺失脚本")]
        public static void CleanMissingScript()
        {
            string[] filePaths = Directory.GetFiles(Application.dataPath, "*.prefab", SearchOption.AllDirectories);
            int sum = 0;
            for (int i = 0; i < filePaths.Length; i++)
            {
                string path = filePaths[i].Replace(Application.dataPath, "Assets");
                GameObject objPrefab = AssetDatabase.LoadAssetAtPath<GameObject>(path);
                GameObject obj = PrefabUtility.InstantiatePrefab(objPrefab) as GameObject;
                //判断是否存在于Hierarchy面板上
                if (obj.hideFlags == HideFlags.None)
                {
                    foreach (var item in obj.GetComponentsInChildren<Transform>(true))
                    {
                        int r = 0;
                        r = GameObjectUtility.RemoveMonoBehavioursWithMissingScript(item.gameObject);
                        if (r > 0)
                        {
                            PrefabUtility.SaveAsPrefabAssetAndConnect(obj, path, InteractionMode.AutomatedAction);
                            AssetDatabase.Refresh();
                        }
                        sum += r;
                        Log.Info("清除了物体：" + item.name + " 的一个missing脚本");
                    }
                    UnityEngine.Object.DestroyImmediate(obj);
                }
            }
            Log.Info("清除完成,清理个数：" + sum);
        }

        [MenuItem("Assets/Create/TCCFramework/创建UIScript",false,100)]
        public static void CreateUIScript()
        {
            CreateScriptFromTemplate.Create<CreateUIScript>(EditorConfigFile.CreateUIScriptTemplatePath, "NewUIScript",
                EditorGUIUtility.IconContent("cs Script Icon").image as Texture2D);
        }
        #endregion

        #region 事件回调
        /// <summary>
        /// 删除数据表事件
        /// </summary>
        /// <param name="instaceId"></param>
        public static void DataTableDeleteEvent(int instaceId)
        {
            Object obj = EditorUtility.InstanceIDToObject(instaceId);
            if (obj != null && obj is DataTable)
            {
                string className = obj.GetType().Name;
                string[] guids = AssetDatabase.FindAssets($"{className} t:Script", new[] { EditorConfigFile.mainTablePath });
                if (guids.Length < 1) return;
                foreach (var item in guids)
                {
                    File.Delete(AssetPathTool.RelativePathToAbsPath(AssetDatabase.GUIDToAssetPath(item)));
                }
            }
        }

        /// <summary>
        /// C#脚本被创建时事件
        /// </summary>
        /// <param name="path">文件路径</param>
        public static void OnCreateScript(string path)
        {
            path = path.Replace(".meta", "");
            if(path.EndsWith(".cs"))
            {
                string codes = File.ReadAllText(path);
                if (codes.Contains("TCC.Framework")) return;
                codes = codes.Insert(0, "using TCC.Framework;\n");
                File.WriteAllText(path, codes);
                AssetDatabase.Refresh();
            }
        }
        #endregion

        #region 日志溯源
        [UnityEditor.Callbacks.OnOpenAsset]
        static bool OnOpenAsset(int instanceID, int line)
        {
            string stackTrace = GetStackTrace();
            if (!string.IsNullOrEmpty(stackTrace) && stackTrace.Contains("【TCC.Framework】:"))
            {
                // 使用正则表达式匹配at的哪个脚本的哪一行
                var matches = Regex.Match(stackTrace, @"\(at (.+)\)", RegexOptions.IgnoreCase);
                string path = "";
                while (matches.Success)
                {
                    string pathLine = matches.Groups[1].Value;

                    if (!pathLine.Contains("Log.cs"))
                    {
                        int splitIndex = pathLine.LastIndexOf(":");
                        // 脚本路径
                        path = pathLine.Substring(0, splitIndex);
                        // 行号
                        line = int.Parse(pathLine.Substring(splitIndex + 1));

                        break;
                    }
                    matches = matches.NextMatch();
                }
                // 跳转到目标代码的特定行
                MonoScript script = AssetDatabase.LoadAssetAtPath<MonoScript>(path);
                if (script != null && script.GetInstanceID() != instanceID)
                {
                    AssetDatabase.OpenAsset(script, line);
                    return true;
                }
                else
                    return false;
            }
            return false;
        }

        /// <summary>
        /// 获取当前日志窗口选中的日志的堆栈信息
        /// </summary>
        /// <returns></returns>
        static string GetStackTrace()
        {
            // 通过反射获取ConsoleWindow类
            System.Type ConsoleWindowType = typeof(EditorWindow).Assembly.GetType("UnityEditor.ConsoleWindow");
            // 获取窗口实例
            FieldInfo fieldInfo = ConsoleWindowType.GetField("ms_ConsoleWindow", BindingFlags.Static | BindingFlags.NonPublic);
            object consoleInstance = fieldInfo.GetValue(null);
            if (consoleInstance != null)
            {
                if ((object)EditorWindow.focusedWindow == consoleInstance)
                {
                    // 获取m_ActiveText成员
                    fieldInfo = ConsoleWindowType.GetField("m_ActiveText", BindingFlags.Instance | BindingFlags.NonPublic);
                    // 获取m_ActiveText的值
                    string activeText = fieldInfo.GetValue(consoleInstance).ToString();
                    return activeText;
                }
            }
            return null;
        }
        #endregion

        #region Hierachy面板监视
        private static void HierarchyItemChanged(int instanceID, Rect selectionRect)
        {
            
        }
        #endregion

        /// <summary>
        /// 编辑器运行前执行
        /// </summary>
        [RuntimeInitializeOnLoadMethod]
        private static void OnEditorRuntime()
        {
            m_onEditorRuntime?.Invoke();
        }
    }
}
